#

import logging

from wglmkapplayer.writer import Writer

LOGGER = logging.getLogger("wglmkapplayer")


# LayerWriter
#
class LayerWriter (Writer) :


    # __init__
    #
    def __init__ (self, basename, layer_name, registry) :
        super().__init__(basename)
        self.layer_name = layer_name
        self.registry = registry


    # write
    #
    def write (self) :
        LOGGER.debug(f"write {self.registry} ...")

        layer_name_l = self.layer_name.lower()
        
        # header
        hpp_name = f"{self.basename}applayer{layer_name_l}.inl.hpp" # [fixme]
        h_file = self.add_file(hpp_name)
        h_root = h_file.root

        guard = '_' + hpp_name.upper().replace('.', '_').replace('-', '_')
        s_guard = h_root.body.section()
        s_guard.head.writeln(f"#ifndef {guard}",
                             f"#define {guard}")
        s_guard.foot.writeln(f"#endif // ifdef {guard}")

        s_wglns = s_guard.body.section(indent_body=True, braces=True)
        s_wglns.head.writeln("namespace wgl")

        # body
        cpp_name = f"{self.basename}applayer{layer_name_l}.inl.cpp" # [fixme]
        c_file = self.add_file(cpp_name)
        c_root = c_file.root

        # go
        self.write_all(s_wglns, c_root)


    # write_all
    #
    def write_all (self, h_top, c_top) :
        self.write_load_layer_vtable(self.registry, h_top, c_top)


    # write_load_layer_vtable
    #
    def write_load_layer_vtable(self, registry, h_top, c_top) : # pylint: disable=unused-argument
        sec_decls = h_top.body.section(indent_body=True, braces='class')
        sec_defs = c_top.body.section()

        sec_decls.head.writeln(f"struct WGL_API {self.layer_name}LayerVTableLoader")
        sec_defs.body.writeln(f"// {self.layer_name}LayerVTableLoader functions")

        sec_decls.body.writeln("static void load_vtable ( AppLayerVTable &vt );")
        sec_load = sec_defs.body.section(indent_body=True, braces=True)
        sec_load.head.writeln(f"void {self.layer_name}LayerVTableLoader::load_vtable ( AppLayerVTable &vt )")

        for func in registry.functions.values() :
            # pylint: disable=line-too-long
            sec_decls.body.writeln(f"static {func.prototype};")

            sec_func = sec_defs.body.section(indent_body=True, braces=True)
            proto = func.get_prototype(name_prefix=f"{self.layer_name}LayerVTableLoader::")
            sec_func.head.writeln(f"{proto}")

            params = func.get_params_names_seq(prepend=('wgl_app_layer',))
            callstr = f"virt_vt->{func.name}({params});"
            if not func.is_void() :
                callstr = "return " + callstr
            sec_func.body.writeln(f"AppLayer &wgl_app_layer = AppLayerMaster::get_current_layer(AppLayerLoader{self.layer_name}::LOADER_ID);",
                                  "AppLayerVTableVirtual *virt_vt = static_cast<AppLayerVTableVirtual *>(wgl_app_layer.data);",
                                  callstr)

            sec_load.body.writeln(f"vt.{func.name} = {self.layer_name}LayerVTableLoader::{func.name};")
